#include <stdio.h>
#include <cmath>


__global__ void my_cuda_func();

int main()
{
    // Call my CUDA kernel function
    dim3 grid_layout(2, 3, 3);
    dim3 block_layout(2, 2, 2);
    my_cuda_func<<<grid_layout, block_layout>>>();
    cudaDeviceSynchronize();
    cudaDeviceProp my_prop;
    int total_thds = grid_layout.z * grid_layout.y * grid_layout.x * \
                     block_layout.z * block_layout.y * block_layout.x;
    printf("Total number of threads is %d!\n", total_thds);
    cudaGetDeviceProperties(&my_prop, 0);
    printf("The NVIDIA GPU name of my PC is %s!\n", my_prop.name);
    printf("The maximum shared memory of NVIDIA GPU of my PC is %zu bytes!\n", my_prop.sharedMemPerBlock);
    printf("The maximum shared memory of NVIDIA GPU of my PC is %zu KB!\n", 
           size_t(my_prop.sharedMemPerBlock / pow(2, 10)));

    return 0;
}

__global__ void my_cuda_func()
{
    auto local_thd_idx = threadIdx.x + threadIdx.y * blockDim.x + \
                         threadIdx.z * blockDim.y * blockDim.x;
    auto thd_per_blk = blockDim.z * blockDim.y * blockDim.x;
    auto blk_idx = blockIdx.x + blockIdx.y * gridDim.x + \
                   blockIdx.z * gridDim.y * gridDim.x;
    auto global_thd_idx = local_thd_idx + thd_per_blk * blk_idx;
    printf("The global index of current thread is: %u...\n", global_thd_idx);
}
